/*
 * FILE: syscall_replace.c
 *
 * Replace System Call
 */

#include <linux/uaccess.h>

#include "get_symbol.h"
#include "write_perm.h"

static DEFINE_SPINLOCK(syscall_replace_lock);

struct syscall_hook {
	void *orig;				//原始系统调用
	unsigned long *dst;			//替换系统调用
	int num;				//系统调用号
};

enum syscall_index{
	EXECVE = 0,
};

asmlinkage int dst_execve(struct filename *, const char __user *const __user *, const char __user *const __user *);
struct syscall_hook g_syscall_hook[] = {
	{NULL, (unsigned long *)dst_execve, __NR_execve},
};

int syscall_replace_init(void){
	int i;
	int syscall_num;

	set_kernel_writable();
	spin_lock(&syscall_replace_lock);
	for(i = 0; i < ARRAY_SIZE(g_syscall_hook); i++){
		syscall_num = g_syscall_hook[i].num;
		g_syscall_hook[i].orig = (unsigned long *)orig_sys_call_table[syscall_num];
		orig_sys_call_table[syscall_num] = (unsigned long)g_syscall_hook[i].dst;
	}
	spin_unlock(&syscall_replace_lock);
	set_kernel_readonly();

	return 0;
}

int syscall_replace_exit(void){
	int i;
	int syscall_num;

	set_kernel_writable();
	spin_lock(&syscall_replace_lock);
	for(i = 0; i < ARRAY_SIZE(g_syscall_hook); i++){
		syscall_num = g_syscall_hook[i].num;
		orig_sys_call_table[syscall_num] = (unsigned long)g_syscall_hook[i].orig;
	}
	spin_unlock(&syscall_replace_lock);
	set_kernel_readonly();

	return 0;
}

static asmlinkage int (*orig_execve)(struct filename *fname, const char __user *const __user *argv, const char __user *const __user * envp);
asmlinkage int dst_execve(struct filename *fname, const char __user *const __user *argv, const char __user *const __user * envp){
	char path[512] = { 0 };
	int n;

	orig_execve = g_syscall_hook[EXECVE].orig;

	n = strncpy_from_user(path, fname->name, 512);
	if(n > 0)
		printk("test %s\n", path);
	else
		printk("test null\n");

	return orig_execve(fname, argv, envp);
}
